﻿using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Web.WebPages.Html;

namespace App_Code
{
    /// <summary>
    /// Summary description for GuestHousesCrud
    /// </summary>
    public class GuestHousesCrudController : IGuestHousesCrudController
    {
        private readonly Dictionary<int, GuestHouseRecord> _records = new Dictionary<int, GuestHouseRecord>();

        public GuestHousesCrudController()
        {
            _records = new Dictionary<int, GuestHouseRecord>();
            GuestHouseDB.GetReports(_records);
        }

        public IEnumerable<SelectListItem> GetLocations()
        {
            var l = new Dictionary<string, object>();
            foreach (var r in _records.Values.Where(r => !l.ContainsKey(r.Location)))
            {
                l.Add(r.Location, "");
            }
            var ll = new List<string>(l.Keys);
            ll.Sort();

            return ll.Select(i => new SelectListItem { Value = i, Text = i }).ToList();
        }

        public IEnumerable<SelectListItem> GetAllOrderedByLocation(string sel)
        {
            var items = new List<SelectListItem>();
            var counts = new Dictionary<string, int>();

            foreach (var r in _records.Keys)
            {
                int count;
                if (!counts.TryGetValue(_records[r].Location, out count))
                {
                    counts.Add(_records[r].Location, 0);
                }
                count++;
                counts[_records[r].Location] = count;

                items.Add(new SelectListItem { Value = "" + r, Text = _records[r].Location + " " + count, Selected = ("" + r == sel) });
            }
            items.Sort(new MyListSorter());
            return items;
        }

        public Dictionary<string, object> GetAttributes()
        {
            return new Dictionary<string, object>
                           {
                               {"onChange", "getGuestHouses();"},
                               {"onkeyup", "getGuestHouses();"},
                               {"style", "height:26px;width:220px;margin-left: 0px"}
                           };
        }

        public Dictionary<string, object> GetAttributesLocations()
        {
            return new Dictionary<string, object>
                           {
                               {"onChange", "getRecord();"},
                               {"onkeyup", "getRecord();"},
                               {"style", "height:26px;width:220px;margin-left: 0px"}
                           };
        }

        public string GetSingleRecordAsHTML(string recordID)
        {
            var sb = new StringBuilder();
            sb.Append("<div class=\"ghrowdark\">");
            GetOneInner(recordID, sb);
            sb.Append("</div>");
            return sb.ToString();
        }
        
        public string GetAllRecordsForLocationAsHTML(string location)
        {
            var locations = GetLocations();
            if (locations.Count() == 0)
            {
                return "";
            }
            if (location == "")
            {
                location = locations.First().Value;
            }

            var sb = new StringBuilder();

            var r = 0;

            foreach (var record in _records)
            {
                if (record.Value.Location == location)
                {
                    sb.Append((r & 1) == 0 ? "<div class=\"ghrowdark\">" : "<div class=\"ghrowlight\">");
                    r++;
                    sb.Append(record.Value);
                    sb.Append("</div>");
                }
            }
            return sb.ToString();
        }
    
        //webRequest.Request.UserHostAddress
        public GuestHouseRecord PageLoad(string ip, NameValueCollection form, ref string record)
        {
            var query = new GuestHouseRecord();

            switch (form["hit"])
            {
                case "Add": // save new
                    query.Record = MakeImpure(form["pure"]);
                    query.Location = MakeImpure(form["location"]);
                    int newID = Add(ip, query);
                    if (newID != -1)
                    {
                        record = "" + newID;
                        return Edit(newID);
                    }
                    return query;
            }

            int recordID;
            if (!int.TryParse(record, out recordID))
            {
                // must be first time around - no record selected
                var l = GetAllOrderedByLocation(record);
                if (l.Count() != 0)
                {
                    record = l.First().Value;
                    int.TryParse(record, out recordID);
                    return Edit(recordID);
                }
                return query;
            }

            switch (form["hit"])
            {
                case "Save":
                    query.Record = MakeImpure(form["pure"]);
                    query.Location = MakeImpure(form["location"]);
                    int newID = Save(ip, recordID, query);
                    if (newID != -1)
                    {
                        record = "" + newID;
                        return Edit(newID); 
                    }
                    return query;

                case "Del":
                    Delete(recordID);
                    GuestHouseDB.HideReport(recordID);
                    // select the first record in the drop down list
                    IEnumerable<SelectListItem> l = GetAllOrderedByLocation(record);
                    if (l.Count() != 0)
                    {
                        record = l.First().Value;
                        int.TryParse(record, out recordID);
                        return Edit(recordID); 
                    }
                    return query;

                case "Edit":
                    return Edit(recordID);
            }
            return query;
        }

        private int Add(string ip, GuestHouseRecord query)
        {
            if (string.IsNullOrWhiteSpace(query.Record))
                return -1;

            int seed = GuestHouseDB.SubmitReport(ip, query);
            if (seed == -1)
                return -1;
            _records.Add(seed, query);
            return seed;
        }

        private void GetOneInner(string recordID, StringBuilder sb)
        {
            if (string.IsNullOrWhiteSpace(recordID))
                return;

            int rID;
            if (!int.TryParse(recordID, out rID))
                return;

            GuestHouseRecord r;
            if (!_records.TryGetValue(rID, out r))
                return;

            sb.Append(r);
        }

        private GuestHouseRecord Edit(int i)
        {
            if (!_records.ContainsKey(i))
            {
                return new GuestHouseRecord("Record " + i + " doesn't exist!", "");
            }

            return _records[i];
        }

        private int Save(string ip, int i, GuestHouseRecord query)
        {
            if (string.IsNullOrWhiteSpace(query.Record))
                return -1;
            int newID = GuestHouseDB.UpdateReport(ip, query, i);
            if (newID == -1)
                return -1;
            _records.Remove(i);
            _records.Add(newID, query);
            return newID;
        }

        private void Delete(int i)
        {
            _records.Remove(i);
        }

        // .NET 4.0 really doesn't like any possibility of HTML injection. De-escape to recover the raw HTML
        private static string MakeImpure(string pure)
        {
            string ret = pure.Replace("<=", "<");
            ret = ret.Replace("&=", "&");
            ret = RemoveDuplicateSpaces(ret);
            ret = ret.Replace("\r\n", "\r");
            ret = RemoveDuplicateReturns(ret);
            ret = ret.Replace("\r ", "\r");
            ret = ret.Replace("\r", "\r\n");
            return ret;
        }

        private static string RemoveDuplicateSpaces(string sz)
        {
            string ret = sz.Replace("  ", " ");
            if (ret.Length != sz.Length)
            {
                ret = RemoveDuplicateSpaces(ret);
            }
            return ret;
        }

        private static string RemoveDuplicateReturns(string sz)
        {
            string ret = sz.Replace("\r\r", "\r");
            if (ret.Length != sz.Length)
            {
                ret = RemoveDuplicateReturns(ret);
            }
            return ret;
        }
    }

    class MyListSorter : IComparer<SelectListItem>
    {
        int IComparer<SelectListItem>.Compare(SelectListItem x, SelectListItem y)
        {
            return x.Text.CompareTo(y.Text);
        }
    }

    public class GuestHouseRecord
    {
        public GuestHouseRecord()
        {
            Record = "";
            Location = "";
        }

        public GuestHouseRecord(string r, string l)
        {
            Record = r;
            Location = l;
        }

        public string Record { get; set; }
        public string Location { get; set; }

        public override string ToString()
        {
            return Record;
        }
    }
}